<template>
  <div class="min-h-screen">
    <!-- 登录页面 -->
    <div v-if="!isLoggedIn" class="flex items-center justify-center min-h-screen bg-gray-100">
      <div class="bg-white rounded-xl shadow-lg p-8 max-w-md w-full">
        <div class="text-center mb-6">
          <i class="fa fa-database text-primary text-4xl mb-4"></i>
          <h1 class="text-2xl font-bold text-gray-800">大模型智能知识库</h1>
          <p class="text-gray-500 mt-2">请登录以访问系统</p>
        </div>
        <div v-if="loginError" class="mb-4 p-3 bg-red-100 text-red-700 rounded-lg">
          {{ loginError }}
        </div>
        <div class="space-y-4">
          <div>
            <label for="username" class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
            <input type="text" id="username" v-model="loginForm.username"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
              placeholder="请输入用户名">
          </div>
          <div>
            <label for="password" class="block text-sm font-medium text-gray-700 mb-1">密码</label>
            <input type="password" id="password" v-model="loginForm.password"
              class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
              placeholder="请输入密码">
          </div>
          <button @click="login" class="w-full px-4 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all">
            登录
          </button>
        </div>
      </div>
    </div>

    <!-- 主界面 (登录后显示) -->
    <div v-else>
      <!-- 顶部导航 -->
      <header class="bg-white shadow-md sticky top-0 z-50">
        <div class="container mx-auto px-4 py-3 flex items-center justify-between">
          <div class="flex items-center space-x-2">
            <i class="fa fa-database text-primary text-2xl"></i>
            <h1 class="text-xl font-bold text-gradient bg-gradient-to-r from-primary to-accent">AI智能知识库</h1>
          </div>
        <div class="hidden md:flex items-center space-x-4">
          <button id="newDocumentBtn" class="flex items-center px-3 py-1 rounded-md hover:bg-gray-100 transition-colors" @click="scrollToAddDocument">
              <i class="fa fa-file-lines text-primary mr-2"></i>
              <span>添加新文档</span>
            </button>
          <!-- <button id="categoryBtn" class="flex items-center px-3 py-1 rounded-md hover:bg-gray-100 transition-colors">
            <i class="fa fa-folder text-primary mr-2"></i>
            <span>管理分类</span>
          </button> -->
          <button id="aboutBtn" class="flex items-center px-3 py-1 rounded-md hover:bg-gray-100 transition-colors">
            <i class="fa fa-info-circle text-primary mr-2"></i>
            <span>关于</span>
          </button>
          <button id="logoutBtn" class="flex items-center px-3 py-1 rounded-md hover:bg-gray-100 transition-colors" @click="logout">
            <i class="fa fa-sign-out text-primary mr-2"></i>
            <span>退出登录</span>
          </button>
        </div>
        <div class="md:hidden">
          <button id="mobileMenuBtn" class="p-2 rounded-md hover:bg-gray-100" @click="toggleMobileMenu">
            <i class="fa fa-bars text-xl"></i>
          </button>
        </div>
      </div>
      <!-- 移动端菜单 -->
      <div id="mobileMenu" class="hidden md:hidden bg-white border-t" v-show="mobileMenuVisible">
        <div class="container mx-auto px-4 py-2 space-y-2">
          <button id="mobileNewDocumentBtn"
              class="w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 flex items-center" @click="scrollToAddDocument">
              <i class="fa fa-file-lines text-primary mr-2"></i>
              <span>添加新文档</span>
            </button>
          <button id="mobileCategoryBtn"
            class="w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 flex items-center">
            <i class="fa fa-folder text-primary mr-2"></i>
            <span>管理分类</span>
          </button>
          <button id="mobileAboutBtn" class="w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 flex items-center">
            <i class="fa fa-info-circle text-primary mr-2"></i>
            <span>关于</span>
          </button>
          <button id="mobileLogoutBtn" class="w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 flex items-center" @click="logout">
            <i class="fa fa-sign-out text-primary mr-2"></i>
            <span>退出登录</span>
          </button>
        </div>
      </div>
    </header>

    <!-- 主内容区 -->
    <main class="container mx-auto px-4 py-6">
      <!-- 主题切换按钮 -->
      <button class="theme-toggle" @click="toggleTheme" aria-label="切换主题">
        <i v-if="darkMode" class="fa fa-sun text-xl"></i>
        <i v-else class="fa fa-moon text-xl"></i>
      </button>
      <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
        <!-- 左侧：输入区域 -->
        <div class="lg:col-span-2 space-y-6">
          <!-- 搜索结果卡片 -->
          <div class="bg-white rounded-xl shadow-soft p-6 transition-all duration-300 hover:shadow-lg">
            <h2 class="text-lg font-bold mb-4 flex items-center">
              <i class="fa fa-search text-primary mr-2"></i>
              搜索结果
            </h2>
            <div class="space-y-4">
              <div class="flex space-x-2">
                <input type="text" id="searchQuery"
                  class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                  placeholder="搜索文档内容..." v-model="searchQuery" @keypress.enter="searchDocuments">
                <select id="searchCategory"
                  class="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                  v-model="searchCategoryId">
                  <option value="">全部分类</option>
                  <option v-for="category in categories" :key="category.id" :value="category.id">{{ category.name }}
                  </option>
                </select>
                <button id="searchBtn"
                  class="px-4 py-2 bg-accent hover:bg-accent/90 text-white font-medium rounded-lg shadow transition-all"
                  @click="searchDocuments">
                  <i class="fa fa-search"></i>
                </button>
              </div>
              <div id="searchResults" class="space-y-4 max-h-96 overflow-y-auto">
                <!-- 搜索结果 -->
                <div v-if="searchLoading" class="text-center text-gray-500 py-6">
                  <i class="fa fa-circle-notch fa-spin text-2xl mb-2"></i>
                  <p>搜索中...</p>
                </div>
                <div v-else-if="searchResults.length === 0 && searchQuery" class="text-center text-gray-500 py-10">
                  <i class="fa fa-search text-4xl mb-2 opacity-50"></i>
                  <p>未找到匹配的文档</p>
                </div>
                <div v-else-if="searchResults.length === 0" class="text-center text-gray-500 py-10">
                  <i class="fa fa-search text-4xl mb-2 opacity-50"></i>
                  <p>请输入关键词进行搜索</p>
                </div>
                <div v-else>
                  <div v-for="result in searchResults" :key="result.id"
                    class="p-4 border border-gray-200 rounded-lg hover:shadow-md transition-all cursor-pointer"
                    @click="showDocumentDetail(result.id)">
                    <div class="flex justify-between items-start mb-2">
                      <h4 class="font-medium text-lg">{{ result.title || '未命名文档' }}</h4>
                      <!-- <span class="text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full">相似度: {{
                        (result.similarity * 100).toFixed(1) }}%</span> -->
                    </div>
                    <div v-if="result.category_ids && result.category_ids.length > 0" class="flex flex-wrap gap-2 mb-2">
                      <span v-for="categoryId in result.category_ids" :key="categoryId"
                        class="text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded-full">
                        {{ getCategoryName(categoryId) }}
                      </span>
                    </div>
                    <div v-else class="text-xs text-gray-400 mb-2">未分类</div>
                    <div class="text-gray-600 mb-2 text-sm markdown-preview"
                      v-html="renderMarkdown(truncateText(result.content, 200))"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 文本输入卡片 -->
          <div id="addDocumentDiv" class="bg-white rounded-xl shadow-soft p-6 transition-all duration-300 hover:shadow-lg">
            <h2 class="text-lg font-bold mb-4 flex items-center">
              <i class="fa fa-pen-to-square text-primary mr-2"></i>
              添加新文档
            </h2>
            <div class="space-y-4">
              <div>
                <label for="documentTitle" class="block text-sm font-medium text-gray-700 mb-1">文档标题（可选）</label>
                <input type="text" id="documentTitle"
                  class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                  placeholder="输入文档标题" v-model="documentForm.title">
              </div>
              <div>
                <div class="flex justify-between items-center mb-1">
                  <label class="block text-sm font-medium text-gray-700">选择分类（可多选）</label>
                  <button v-if="documentForm.content.trim()" id="smartCategorizeBtn"
                    class="text-xs px-2 py-1 bg-neon-green hover:bg-neon-green font-bold rounded-md transition-colors flex items-center"
                    @click="smartCategorize">
                    <i class="fa fa-magic mr-1"></i>
                    智能分类
                  </button>
                </div>
                <div class="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto">
                  <label v-for="category in categories" :key="category.id"
                    class="flex items-center space-x-2 p-2 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50 transition-colors">
                    <input type="checkbox" :value="category.id" v-model="documentForm.categoryIds"
                      class="w-4 h-4 text-primary focus:ring-primary border-gray-300 rounded">
                    <span>{{ category.name }}</span>
                  </label>
                </div>
                <p v-if="categories.length === 0" class="text-sm text-gray-500 mt-1">暂无分类，请先添加分类</p>
              </div>
              <div>
                <label for="documentContent" class="block text-sm font-medium text-gray-700 mb-1">文档内容</label>
                <textarea id="documentContent" rows="8"
                  class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all resize-none"
                  placeholder="在此输入Markdown文档内容...&#10;支持 # 标题、**粗体**、*斜体*、- 列表 等Markdown语法"
                  v-model="documentForm.content"></textarea>
              </div>
              <div class="flex justify-end">
                <button id="formatDocumentBtn"
                  class="mr-3 px-6 py-2 bg-orange hover:bg-orange text-white font-medium rounded-lg shadow transition-all flex items-center"
                  @click="formatDocumentContent('create')" :disabled="formatLoading">
                  <i v-if="!formatLoading" class="fa fa-magic mr-2"></i>
                  <i v-else class="fas fa-circle-notch fa-spin mr-2"></i>
                  {{ formatLoading ? '排版中...' : '一键排版' }}
                </button>
                <button v-if="canUndo"
                  class="mr-3 px-6 py-2 bg-light-pink hover:bg-light-pink text-white font-medium rounded-lg shadow transition-all flex items-center"
                  @click="undoFormat('create')">
                  <i class="fa fa-undo mr-2"></i>
                  撤销
                </button>
                <button id="saveDocumentBtn"
                  class="px-6 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all flex items-center"
                  @click="saveDocument">
                  <i class="fa fa-save mr-2"></i>
                  保存文档
                </button>
              </div>
            </div>
          </div>


        </div>

        <!-- 右侧：分类和最近文档 -->
        <div class="space-y-6">
          <!-- 分类卡片 -->
          <div class="bg-white rounded-xl shadow-soft p-6 transition-all duration-300 hover:shadow-lg">
            <h2 class="text-lg font-bold mb-4 flex items-center justify-between">
              <span><i class="fa fa-folder text-primary mr-2"></i>文档分类</span>
              <div class="flex items-center space-x-2">
                <button id="editCategoriesBtn"
                  :class="['text-primary hover:text-primary/80 transition-colors', isCategoriesEditMode ? 'animate-pulse' : '']"
                  @click="isCategoriesEditMode = !isCategoriesEditMode"
                  :title="isCategoriesEditMode ? '退出编辑模式' : '进入编辑模式'">
                  <i class="fa fa-pencil"></i>
                </button>
                <button id="addCategoryBtn" class="text-primary hover:text-primary/80 transition-colors"
                  @click="showAddCategoryModal">
                  <i class="fa fa-plus-circle"></i>
                </button>
              </div>
            </h2>
            <div id="categoriesList" class="space-y-2 max-h-80 overflow-y-auto">
              <div v-if="categories.length === 0" class="text-center text-gray-500 py-6">
                <i class="fa fa-folder-open-o text-2xl mb-2 opacity-50"></i>
                <p>暂无分类</p>
              </div>
              <div v-else>
                <div v-for="category in categories" :key="category.id"
                  class="flex items-center justify-between p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
                  @click="isCategoriesEditMode ? showEditCategoryModal(category) : getDocumentsByCategory(category.id)">
                  <div class="flex items-center">
                    <i class="fa fa-folder text-primary mr-3"></i>
                    <div>
                      <div class="font-medium">{{ category.name }}</div>
                      <div v-if="category.description" class="text-xs text-gray-500">{{
                        truncateText(category.description, 30) }}</div>
                    </div>
                  </div>
                  <div class="flex items-center">
                    <span class="text-sm text-gray-500">{{ category.documentCount || 0 }} 文档</span>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 最近文档卡片 -->
          <div class="bg-white rounded-xl shadow-soft p-6 transition-all duration-300 hover:shadow-lg">
            <h2 class="text-lg font-bold mb-4 flex items-center">
              <i class="fa fa-clock text-primary mr-2"></i>
              最近文档
            </h2>
            <div id="recentDocuments" class="space-y-3 max-h-64 overflow-y-auto">
              <div v-if="recentDocumentsLoading" class="text-center text-gray-500 py-6">
                <i class="fa fa-circle-notch fa-spin text-2xl mb-2"></i>
                <p>加载中...</p>
              </div>
              <div v-else-if="recentDocuments.length === 0" class="text-center text-gray-500 py-6">
                <i class="fa fa-file-lines text-2xl mb-2 opacity-50"></i>
                <p>暂无文档</p>
              </div>
              <div v-else>
                <div v-for="document in recentDocuments" :key="document.id"
                  class="p-3 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
                  @click="showDocumentDetail(document.id)">
                  <div class="font-medium mb-1">{{ document.title || '未命名文档' }}</div>
                  <div v-if="document.category_ids && document.category_ids.length > 0"
                    class="flex flex-wrap gap-1 mb-1">
                    <span v-for="categoryId in document.category_ids" :key="categoryId"
                      class="text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full">
                      {{ getCategoryName(categoryId) }}
                    </span>
                  </div>
                  <div v-else class="text-xs text-gray-400 mb-1">未分类</div>
                  <div class="text-sm text-gray-600 line-clamp-2 markdown-preview"
                    v-html="renderMarkdown(truncateText(document.content, 60))"></div>
                </div>
              </div>
            </div>
          </div>

          <!-- 统计信息卡片 -->
          <div
            class="bg-gradient-to-br from-primary to-accent text-white rounded-xl shadow-soft p-6 transition-all duration-300 hover:shadow-lg">
            <h2 class="text-lg font-bold mb-4">知识库统计</h2>
            <div class="grid grid-cols-2 gap-4">
              <div class="text-center">
                <div class="text-3xl font-bold">{{ totalDocuments }}</div>
                <div class="text-sm opacity-80">总文档数</div>
              </div>
              <div class="text-center">
                <div class="text-3xl font-bold">{{ categories.length }}</div>
                <div class="text-sm opacity-80">总分类数</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-white border-t mt-10 py-6">
      <div class="container mx-auto px-4 text-center text-gray-600">
        <p>&copy; 2025 AI智能知识库 - 智能文本分类与检索系统</p>
      </div>
    </footer>
  </div>

    <!-- 模态框：添加分类 -->
    <div id="addCategoryModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="addCategoryModalVisible" @click.self="hideAddCategoryModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold">添加新分类</h3>
            <button id="closeCategoryModal" class="text-gray-500 hover:text-gray-700" @click="hideAddCategoryModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <div>
              <label for="categoryName" class="block text-sm font-medium text-gray-700 mb-1">分类名称</label>
              <input type="text" id="categoryName"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                placeholder="输入分类名称" v-model="categoryForm.name">
            </div>
            <div>
              <label for="categoryDescription" class="block text-sm font-medium text-gray-700 mb-1">分类描述（可选）</label>
              <textarea id="categoryDescription" rows="3"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all resize-none"
                placeholder="输入分类描述" v-model="categoryForm.description"></textarea>
            </div>
            <div class="flex justify-end space-x-3">
              <button id="cancelAddCategory"
                class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                @click="hideAddCategoryModal">取消</button>
              <button id="confirmAddCategory"
                class="px-4 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all"
                @click="addCategory">添加</button>
            </div>
          </div>
        </div>
      </transition>
    </div>

    <!-- 模态框：文档详情 -->
    <div id="documentDetailModal"
      class="fixed inset-0 bg-black bg-opacity-50 flex flex-col items-center justify-center z-50"
      v-show="documentDetailModalVisible" @click.self="hideDocumentDetailModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-5xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold">{{ currentDocument?.title || '文档详情' }}</h3>
            <button id="closeDocumentDetailModal" class="text-gray-500 hover:text-gray-700"
              @click="hideDocumentDetailModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>

          <!-- 文档详情和聊天区域 - 响应式布局 -->
          <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 flex-1 min-h-0 overflow-hidden">
            <!-- 左侧：文档内容 -->
            <div class="lg:col-span-2 overflow-y-auto p-2">
              <div class="space-y-4">
                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-1">分类</label>
                  <div id="documentDetailCategory" class="px-4 py-2 bg-gray-50 rounded-lg border border-gray-200">
                    <span
                      v-if="!currentDocument || !currentDocument.category_ids || currentDocument.category_ids.length === 0">未分类</span>
                    <div v-else class="flex flex-wrap gap-2">
                      <span v-for="categoryId in currentDocument.category_ids" :key="categoryId"
                        class="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">{{ getCategoryName(categoryId)
                        }}</span>
                    </div>
                  </div>
                </div>
                <div>
                  <label class="block text-sm font-medium text-gray-700 mb-1">内容</label>
                  <div id="documentDetailContentText"
                    class="px-4 py-2 bg-gray-50 rounded-lg border border-gray-200 whitespace-pre-wrap break-words markdown-content"
                    v-html="renderMarkdown(currentDocument?.content)"></div>
                </div>
                <div class="flex justify-between text-sm text-gray-500">
                  <span id="documentDetailCreatedAt" v-if="currentDocument">创建时间: {{
                    formatDate(currentDocument.created_at) }}</span>
                  <span id="documentDetailUpdatedAt" v-if="currentDocument">更新时间: {{
                    formatDate(currentDocument.updated_at) }}</span>
                </div>
              </div>
            </div>

            <!-- 聊天区域和拖动条容器 -->
            <div class="flex items-start h-full">
              <!-- 右侧：聊天功能 -->
              <div id="chatContainer"
                class="flex-1 flex flex-col border border-gray-200 rounded-lg min-w-[300px] h-full"
                style="width: 400px; overflow: hidden">
                <!-- 对话列表区域 -->
                <div class="p-2 border-b border-gray-200 bg-gray-50">
                  <div class="flex justify-between items-center mb-2">
                    <h4 class="font-medium">对话</h4>
                    <button class="text-primary hover:text-primary/80 transition-colors text-sm"
                      @click="createNewConversation(currentDocument.id)">
                      <i class="fa fa-plus-circle mr-1"></i> 新建
                    </button>
                  </div>
                  <div id="conversationsList" class="max-h-40 overflow-y-auto space-y-1">
                    <div v-if="loadingConversation" class="text-center text-gray-500 py-2">
                      <i class="fa fa-circle-notch fa-spin"></i> 加载中...
                    </div>
                    <div v-else-if="conversations.length === 0" class="text-center text-gray-500 py-4 text-sm">
                      暂无对话，点击上方"新建"按钮开始对话
                    </div>
                    <div v-else>
                      <div v-for="conversation in conversations" :key="conversation.id"
                        class="p-2 rounded-md cursor-pointer hover:bg-gray-100 transition-colors"
                        :class="{ 'bg-primary/10 border-l-2 border-primary': currentConversation && currentConversation.id === conversation.id }"
                        @click="switchConversation(conversation.id)">
                        <div class="flex justify-between items-start">
                          <div class="font-medium text-sm truncate w-44">
                            {{ conversation.title }}
                          </div>
                          <button class="text-blue-500 hover:text-blue-600 text-xs transition-colors ml-1"
                            @click.stop="showRenameConversationModal(conversation.id, conversation.title)" title="修改对话">
                            <i class="fa fa-pencil"></i>
                          </button>
                        </div>
                        <div class="text-xs text-gray-500 truncate">
                          更新时间: {{ formatDate(conversation.updated_at) }}
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                <!-- 消息显示区域 -->
                <div id="messagesContainer" class="flex-1 overflow-y-auto p-3 bg-gray-50 min-h-0"
                  style="max-height: calc(73vh - 280px);">
                  <div v-if="loadingConversation" class="text-center text-gray-500 py-6">
                    <i class="fa fa-circle-notch fa-spin text-xl mb-2"></i>
                    <p>加载对话中...</p>
                  </div>
                  <div v-else-if="!currentConversation" class="text-center text-gray-500 py-10">
                    <i class="fa fa-comments-o text-4xl mb-2 opacity-50"></i>
                    <p>请选择一个对话或创建新对话</p>
                  </div>
                  <div v-else>
                    <div v-if="messages.length === 0" class="text-center text-gray-500 py-6">
                      <p>开始与智能助手的对话吧！</p>
                    </div>
                    <div class="space-y-4">
                      <!-- 用户消息 -->
                      <div v-for="message in messages" :key="message.id"
                        :class="message.role === 'user' ? 'flex justify-end' : 'flex justify-start'">
                        <div class="max-w-[85%] rounded-lg p-3 shadow-sm">
                          <div v-if="message.role === 'user'" class="bg-primary text-white rounded-tr-none">
                            <div class="text-right mb-1 text-xs opacity-70">你</div>
                            <div class="text-left whitespace-pre-wrap">{{ message.content }}</div>
                          </div>
                          <div v-else class="bg-white border border-gray-200 rounded-tl-none">
                            <div class="text-left mb-1 text-xs text-gray-500">智能助手</div>
                            <div class="text-left whitespace-pre-wrap" v-html="renderMarkdown(message.content)"></div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>

                <!-- 消息输入区域 -->
                <div v-if="currentConversation" class="p-2 border-t border-gray-200 flex-shrink-0">
                  <form @submit.prevent="sendMessage">
                    <div class="flex gap-2">
                      <input type="text" v-model="newMessage" placeholder="输入问题，按Enter发送..."
                        class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                        :disabled="sendingMessage">
                      <button type="submit"
                        class="px-4 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all"
                        :disabled="!newMessage.trim() || sendingMessage">
                        <i v-if="sendingMessage" class="fa fa-circle-notch fa-spin"></i>
                        <i v-else class="fa fa-paper-plane"></i>
                      </button>
                    </div>
                  </form>
                </div>
              </div>
              <!-- 拖动条 -->
              <div id="chatResizeHandle"
                class="w-2 bg-gray-200 cursor-col-resize hover:bg-gray-300 transition-colors rounded-r-lg"
                @mousedown="startResizing"></div>
            </div>
          </div>

          <!-- 底部按钮 - 现在固定在底部 -->
          <div class="flex justify-end pt-4 border-t border-gray-200 mt-4">
            <button id="deleteDocumentBtn"
              class="mr-3 px-4 py-2 bg-red-500 hover:bg-red-600 text-white font-medium rounded-lg shadow transition-all"
              @click="confirmDeleteDocument">删除</button>
            <button id="editDocumentBtn"
              class="mr-3 px-4 py-2 bg-green hover:bg-green text-white font-medium rounded-lg shadow transition-all"
              @click="showEditDocumentModal">编辑</button>
            <button id="closeDocumentDetailBtn"
              class="px-4 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all"
              @click="hideDocumentDetailModal">关闭</button>
          </div>
        </div>
      </transition>
    </div>

    <!-- 模态框：编辑文档 -->
    <div id="editDocumentModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="editDocumentModalVisible" @click.self="hideEditDocumentModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-3xl w-full mx-4 max-h-[90vh] overflow-y-auto">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold">编辑文档</h3>
            <button id="closeEditDocumentModal" class="text-gray-500 hover:text-gray-700"
              @click="hideEditDocumentModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <div>
              <label for="editDocumentTitle" class="block text-sm font-medium text-gray-700 mb-1">文档标题（可选）</label>
              <input type="text" id="editDocumentTitle"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                placeholder="输入文档标题" v-model="editDocumentForm.title">
            </div>
            <div>
              <div class="flex justify-between items-center mb-1">
                <label class="block text-sm font-medium text-gray-700">选择分类（可多选）</label>
                <button v-if="editDocumentForm.content.trim()" id="smartCategorizeEditBtn"
                  class="text-xs px-2 py-1 bg-neon-green hover:bg-neon-green font-bold rounded-md transition-colors flex items-center"
                  @click="smartCategorize">
                  <i class="fa fa-magic mr-1"></i>
                  智能分类
                </button>
              </div>
              <div class="grid grid-cols-2 gap-2 max-h-40 overflow-y-auto">
                <label v-for="category in categories" :key="category.id"
                  class="flex items-center space-x-2 p-2 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50 transition-colors">
                  <input type="checkbox" :value="category.id" v-model="editDocumentForm.categoryIds"
                    class="w-4 h-4 text-primary focus:ring-primary border-gray-300 rounded">
                  <span>{{ category.name }}</span>
                </label>
              </div>
              <p v-if="categories.length === 0" class="text-sm text-gray-500 mt-1">暂无分类，请先添加分类</p>
            </div>
            <div>
              <label for="editDocumentContent" class="block text-sm font-medium text-gray-700 mb-1">文档内容</label>
              <textarea id="editDocumentContent" rows="12"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all resize-none"
                placeholder="在此输入Markdown文档内容..." v-model="editDocumentForm.content"></textarea>
            </div>
            <div class="flex justify-end space-x-3">
              <button id="cancelEditDocument"
                class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                @click="hideEditDocumentModal">取消</button>
              <button id="formatEditDocumentBtn"
                class="px-4 py-2 bg-orange hover:bg-orange text-white font-medium rounded-lg shadow transition-all"
                @click="formatDocumentContent('edit')" :disabled="formatLoading">
                <i v-if="!formatLoading" class="fa fa-magic mr-2"></i>
                <i v-else class="fas fa-circle-notch fa-spin mr-2"></i>
                {{ formatLoading ? '排版中...' : '一键排版' }}
              </button>
              <button v-if="canUndo"
                class="px-4 py-2 bg-light-pink hover:bg-light-pink text-white font-medium rounded-lg shadow transition-all"
                @click="undoFormat('edit')"><i class="fa fa-undo mr-2"></i>撤销</button>
              <button id="saveEditDocument"
                class="px-4 py-2 bg-green hover:bg-green text-white font-medium rounded-lg shadow transition-all"
                @click="handleSaveEditDocument">保存修改</button>
            </div>
          </div>
        </div>
      </transition>
    </div>

    <!-- Toast提示 -->
    <div v-if="toast.visible"
      :class="['fixed top-4 right-4 px-4 py-2 rounded-lg shadow-lg transform transition-all duration-500 z-50', toast.type === 'success' ? 'bg-green-500 text-white' : 'bg-red-500 text-white']"
      :style="{ transform: toast.visible ? 'translateX(0)' : 'translateX(100%)' }">
      <i v-if="toast.type === 'success'" class="fa fa-check-circle mr-2"></i>
      <i v-else class="fa fa-exclamation-circle mr-2"></i>
      {{ toast.message }}
    </div>

    <!-- 模态框：删除对话确认 -->
    <div id="deleteConversationModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="deleteConversationModalVisible" @click.self="hideDeleteConversationModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold text-red-500"><i class="fa fa-trash-o mr-2"></i>删除对话</h3>
            <button class="text-gray-500 hover:text-gray-700" @click="hideDeleteConversationModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <p class="">确定要删除这个对话吗？删除后将无法恢复。</p>
            <div class="p-3 rounded-lg border border-gray-700">
              <p class="text-sm font-medium text-gray-70 mb-1">对话标题：</p>
              <p class="text-sm text-gray-60">{{ currentOperationConversationTitle }}</p>
            </div>
            <div class="flex justify-end space-x-3">
              <button id="cancelDeleteConversation"
                class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                @click="hideDeleteConversationModal">取消</button>
              <button
                class="px-4 py-2 bg-red-500 hover:bg-red-600 text-white font-medium rounded-lg shadow transition-all"
                @click="confirmDeleteConversation">确认删除</button>
            </div>
          </div>
        </div>
      </transition>
    </div>

    <!-- 模态框：重命名对话 -->
    <div id="renameConversationModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="renameConversationModalVisible" @click.self="hideRenameConversationModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold"><i class="fa fa-pencil mr-2"></i>重命名对话</h3>
            <button class="text-gray-500 hover:text-gray-700" @click="hideRenameConversationModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">当前标题：</label>
              <div class="p-2 bg-gray-50 rounded-lg border border-gray-200 text-gray-600">
                {{ currentOperationConversationTitle }}
              </div>
            </div>
            <div>
              <label for="newConversationTitle" class="block text-sm font-medium text-gray-700 mb-1">新标题：</label>
              <input type="text" id="newConversationTitle"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                placeholder="输入新的对话标题" v-model="newConversationTitle" @keydown.enter="confirmRenameConversation">
            </div>
            <div class="flex justify-between space-x-3">
              <button
                class="px-4 py-2 bg-red-500 hover:bg-red-600 text-white font-medium rounded-lg shadow transition-all"
                @click.stop="showDeleteConversationModal(currentOperationConversationId, currentOperationConversationTitle)">删除对话</button>
              <div class="flex space-x-3">
                <button id="cancelRenameConversation"
                  class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                  @click="hideRenameConversationModal">取消</button>
                <button
                  class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg shadow transition-all"
                  @click="confirmRenameConversation" :disabled="!newConversationTitle.trim()">确认修改</button>
              </div>
            </div>
          </div>
        </div>
      </transition>
    </div>

    <!-- 模态框：编辑分类 -->
    <div id="editCategoryModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="editCategoryModalVisible" @click.self="hideEditCategoryModal">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold">编辑分类</h3>
            <button id="closeEditCategoryModal" class="text-gray-500 hover:text-gray-700"
              @click="hideEditCategoryModal">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <div>
              <label for="editCategoryName" class="block text-sm font-medium text-gray-700 mb-1">分类名称</label>
              <input type="text" id="editCategoryName"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all"
                placeholder="输入分类名称" v-model="editCategoryForm.name">
            </div>
            <div>
              <label for="editCategoryDescription" class="block text-sm font-medium text-gray-700 mb-1">分类描述（可选）</label>
              <textarea id="editCategoryDescription" rows="3"
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary outline-none transition-all resize-none"
                placeholder="输入分类描述" v-model="editCategoryForm.description"></textarea>
            </div>
            <div class="flex justify-end space-x-3">
              <button id="cancelEditCategory"
                class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                @click="hideEditCategoryModal">取消</button>
              <button id="confirmEditCategory"
                class="px-4 py-2 bg-green hover:bg-green text-white font-medium rounded-lg shadow transition-all"
                @click="updateCategory">保存修改</button>
            </div>
          </div>
        </div>
      </transition>
    </div>

    <!-- 模态框：智能分类结果 -->
    <div id="smartCategoriesModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
      v-show="smartCategoriesModalVisible" @click.self="smartCategoriesModalVisible = false">
      <transition name="modal">
        <div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
          <div class="flex justify-between items-center mb-4">
            <h3 class="text-xl font-bold"><i class="fa fa-magic mr-2"></i>智能分类结果</h3>
            <button class="text-gray-500 hover:text-gray-700" @click="smartCategoriesModalVisible = false">
              <i class="fa fa-times text-xl"></i>
            </button>
          </div>
          <div class="space-y-4">
            <p>系统为您的文档推荐了以下分类，请选择要应用的分类：</p>
            <div class="space-y-2">
              <label v-for="(category, index) in suggestedCategories" :key="index"
                class="flex items-center space-x-2 p-3 border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50 transition-colors">
                <input type="checkbox" :value="category.name" v-model="selectedCategories"
                  class="w-4 h-4 text-primary focus:ring-primary border-gray-300 rounded">
                <span>{{ category.name }}</span>
                <span v-if="!category.is_existing" class="ml-2 text-xs text-blue-500 bg-blue-50 px-1.5 py-0.5 rounded">
                  新增
                </span>
              </label>
            </div>
            <div class="flex justify-end space-x-3">
              <button id="cancelSmartCategories"
                class="px-4 py-2 border border-gray-300 font-medium rounded-lg hover:bg-gray-50 transition-all"
                @click="smartCategoriesModalVisible = false">取消</button>
              <button
                class="px-4 py-2 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg shadow transition-all"
                @click="confirmSmartCategories">确认</button>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import { Marked } from 'marked'
import { markedHighlight } from 'marked-highlight'
import hljs from 'highlight.js'
import './markdown-styles.css'
import './main-styles.css'
import './dark-mode.css'
import './dark-markdown-styles.css'

// 创建Marked实例并配置highlight.js
const marked = new Marked(
  markedHighlight({
    async: false,
    langPrefix: 'language-',
    highlight: (code) => {
      return hljs.highlightAuto(code).value
    }
  })
)

export default {
  name: 'App',
  data() {
    return {
      isResizing: false,
      initialX: 0,
      initialChatWidth: 0,
      // API基础URL
      API_BASE_URL: '/api',
      
      // 登录状态
      isLoggedIn: false,
      loginForm: {
        username: '',
        password: ''
      },
      loginMessage: '',

      // 移动端菜单状态
      mobileMenuVisible: false,

      // 暗黑模式状态
      darkMode: localStorage.getItem('theme') === 'dark' || false,

      // 分类数据
      categories: [],

      // 文档表单数据
      documentForm: {
        title: '',
        content: '',
        categoryIds: []
      },

      // 搜索数据
      searchQuery: '',
      searchCategoryId: '',
      searchResults: [],
      searchLoading: false,

      // 最近文档
      recentDocuments: [],
      recentDocumentsLoading: false,

      // 统计数据
      totalDocuments: 0,

      // 添加分类模态框
      addCategoryModalVisible: false,
      categoryForm: {
        name: '',
        description: ''
      },

      // 编辑分类模态框
      editCategoryModalVisible: false,
      editCategoryForm: {
        id: null,
        name: '',
        description: ''
      },

      // 分类编辑模式
      isCategoriesEditMode: false,

      // 文档详情模态框
      documentDetailModalVisible: false,
      currentDocument: null,

      // 聊天功能
      conversations: [],
      currentConversation: null,
      messages: [],
      newMessage: '',
      loadingConversation: false,
      sendingMessage: false,

      // 编辑文档模态框
      editDocumentModalVisible: false,
      editDocumentForm: {
        id: null,
        title: '',
        content: '',
        categoryIds: []
      },

      // Toast提示
      toast: {
        visible: false,
        message: '',
        type: 'success' // 'success' or 'error'
      },

      // 对话操作模态框
      deleteConversationModalVisible: false,
      renameConversationModalVisible: false,

      // 排版相关状态
      lastContent: '',
      canUndo: false,
      formatLoading: false,
      currentOperationConversationId: null,
      currentOperationConversationTitle: '',
      newConversationTitle: '',

      // 智能分类相关
      smartCategoriesModalVisible: false,
      suggestedCategories: [],
      selectedCategories: [],

      // 排版功能相关
      lastContent: '', // 用于撤销操作的上一次内容
      canUndo: false // 是否可以撤销排版
    }
  },
  mounted() {
    this.initTheme()
    // 根据当前主题导入对应的highlight.js样式
    this.loadHighlightStyles()
    
    // 添加axios拦截器来处理认证
    axios.interceptors.request.use(config => {
      // 如果请求的URL是登录接口，则不添加token
      if (config.url && (config.url.includes('/token') || config.url.includes('/verify'))) {
        return config
      }
      
      // 从localStorage中获取token
      const token = localStorage.getItem('authToken')
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }
      return config
    }, error => {
      return Promise.reject(error)
    })
    
    // 检查登录状态
    this.checkLoginStatus()
    
    // 如果已经登录，则初始化应用
    if (this.isLoggedIn) {
      this.initApp()
    }
    this.initMathJax()

    // 监听DOM更新后触发MathJax渲染
    this.$watch('currentDocument', () => {
      setTimeout(() => this.renderMathJax(), 0)
    })
    this.$watch('searchResults', () => {
      setTimeout(() => this.renderMathJax(), 0)
    })
    this.$watch('recentDocuments', () => {
      setTimeout(() => this.renderMathJax(), 0)
    })
    // 监听聊天消息更新后触发MathJax渲染公式
    this.$watch('messages', () => {
      setTimeout(() => this.renderMathJax(), 0)
    }, { deep: true })
  },
  methods: {
    // 拖动条相关方法
    startResizing(e) {
      this.isResizing = true;
      this.initialX = e.clientX;
      const chatContainer = document.getElementById('chatContainer');
      this.initialChatWidth = chatContainer.offsetWidth;

      // 添加事件监听器
      document.addEventListener('mousemove', this.onResize);
      document.addEventListener('mouseup', this.stopResizing);
      e.preventDefault();
    },

    onResize(e) {
      if (!this.isResizing) return;

      // 计算新的宽度（从右往左拖动时宽度增加）
      const deltaX = this.initialX - e.clientX;
      let newWidth = this.initialChatWidth - deltaX;

      // 设置最小和最大宽度限制
      const minWidth = 300;
      const maxWidth = window.innerWidth * 0.7; // 最大宽度为窗口的70%
      newWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));

      // 应用新宽度
      const chatContainer = document.getElementById('chatContainer');
      chatContainer.style.width = `${newWidth}px`;
      chatContainer.style.flex = 'none'; // 禁用flex增长
    },

    stopResizing() {
      this.isResizing = false;
      // 移除事件监听器
      document.removeEventListener('mousemove', this.onResize);
      document.removeEventListener('mouseup', this.stopResizing);
    },
    // 初始化应用
    async initApp() {
      await this.updateCategories()
      await this.loadRecentDocuments()
      await this.updateStatistics()
    },

    // 切换移动端菜单
    toggleMobileMenu() {
      this.mobileMenuVisible = !this.mobileMenuVisible
    },

    // 更新分类列表
    async updateCategories() {
      try {
        const response = await axios.get(`${this.API_BASE_URL}/categories/`)
        this.categories = response.data

        // 为每个分类获取文档数量
        for (const category of this.categories) {
          try {
            const docsResponse = await axios.get(`${this.API_BASE_URL}/documents/category/${category.id}`)
            category.documentCount = docsResponse.data.length
          } catch (error) {
            console.error(`获取分类 ${category.name} 的文档数量失败:`, error)
            category.documentCount = 0
          }
        }
      } catch (error) {
        console.error('获取分类失败:', error)
        this.categories = []
      }
    },

    // 显示添加分类模态框
    showAddCategoryModal() {
      this.categoryForm = {
        name: '',
        description: ''
      }
      this.addCategoryModalVisible = true
    },

    // 隐藏添加分类模态框
    hideAddCategoryModal() {
      this.addCategoryModalVisible = false
    },

    // 显示编辑分类模态框
    showEditCategoryModal(category) {
      this.editCategoryForm = {
        id: category.id,
        name: category.name,
        description: category.description || ''
      }
      this.editCategoryModalVisible = true
    },

    // 隐藏编辑分类模态框
    hideEditCategoryModal() {
      this.editCategoryModalVisible = false
      this.editCategoryForm = {
        id: null,
        name: '',
        description: ''
      }
    },

    // 更新分类
    async updateCategory() {
      const name = this.editCategoryForm.name.trim()
      const description = this.editCategoryForm.description.trim()
      const categoryId = this.editCategoryForm.id

      if (!name) {
        this.showErrorToast('请输入分类名称')
        return
      }

      try {
        await axios.put(`${this.API_BASE_URL}/categories/${categoryId}`, {
          name,
          description
        })
        this.hideEditCategoryModal()
        await this.updateCategories()
        this.showSuccessToast('分类更新成功')
      } catch (error) {
        console.error('更新分类失败:', error)
        this.showErrorToast('更新分类失败: ' + (error.response?.data?.detail || error.message))
      }
    },

    // 添加分类
    async addCategory() {
      const name = this.categoryForm.name.trim()
      const description = this.categoryForm.description.trim()

      if (!name) {
        this.showErrorToast('请输入分类名称')
        return
      }

      try {
        await axios.post(`${this.API_BASE_URL}/categories/`, {
          name,
          description
        })
        this.hideAddCategoryModal()
        await this.updateCategories()
        this.showSuccessToast('分类添加成功')
      } catch (error) {
        console.error('添加分类失败:', error)
        this.showErrorToast('添加分类失败: ' + (error.response?.data?.detail || error.message))
      }
    },

    // 保存文档
    async saveDocument() {
      const title = this.documentForm.title.trim()
      const content = this.documentForm.content.trim()
      const categoryIds = this.documentForm.categoryIds.length > 0 ? this.documentForm.categoryIds : []

      if (!content) {
        this.showErrorToast('请输入文档内容')
        return
      }

      try {
        this.recentDocumentsLoading = true
        await axios.post(`${this.API_BASE_URL}/documents/`, {
          title,
          content,
          category_ids: categoryIds
        })

        // 清空表单
        this.documentForm = {
          title: '',
          content: '',
          categoryIds: []
        }

        // 更新统计、最近文档和分类文档数量
        await this.updateStatistics()
        await this.loadRecentDocuments()
        await this.updateCategories()

        this.showSuccessToast('文档保存成功')
      } catch (error) {
        console.error('保存文档失败:', error)
        this.showErrorToast('保存文档失败: ' + (error.response?.data?.detail || error.message))
      } finally {
        this.recentDocumentsLoading = false
        // 重置排版状态
        this.canUndo = false
      }
    },

    // 一键排版文档内容
    async formatDocumentContent(mode) {
      const content = mode === 'create' ? this.documentForm.content : this.editDocumentForm.content

      if (!content.trim()) {
        this.showErrorToast('请先输入文档内容')
        return
      }

      // 设置加载状态
      this.formatLoading = true

      // 保存当前内容用于撤销
      this.lastContent = content
      this.canUndo = false

      try {
        // 调用大模型API进行Markdown排版
        const response = await axios.post(`${this.API_BASE_URL}/documents/format-markdown`, {
          content: content
        })

        // 更新文档内容
        if (mode === 'create') {
          this.documentForm.content = response.data.formatted_content
        } else {
          this.editDocumentForm.content = response.data.formatted_content
        }

        // 排版完成，启用撤销按钮
        this.canUndo = true
        this.showSuccessToast('文档排版成功')
      } catch (error) {
        console.error('排版失败:', error)
        // 如果API调用失败，使用本地简单的格式化处理作为降级方案
        this.fallbackFormatContent(mode)
        // 降级格式化后也启用撤销按钮
        this.canUndo = true
        this.showErrorToast('排版API调用失败，已使用本地格式化方案')
      } finally {
        // 无论成功失败，都重置加载状态
        this.formatLoading = false
      }
    },

    // 撤销排版
    undoFormat(mode) {
      if (!this.canUndo) return

      if (mode === 'create') {
        this.documentForm.content = this.lastContent
      } else {
        this.editDocumentForm.content = this.lastContent
      }

      this.canUndo = false
      this.showSuccessToast('已撤销排版')
    },

    // 降级格式化方案
    fallbackFormatContent(mode) {
      const content = mode === 'create' ? this.documentForm.content : this.editDocumentForm.content

      // 简单的本地Markdown格式化逻辑
      let formatted = content

      // 修复标题格式
      formatted = formatted.replace(/^#(?!\s)/gm, '# ')
      formatted = formatted.replace(/^(##+)(?!\s)/gm, '$1 ')

      // 修复列表格式
      formatted = formatted.replace(/^[-*](?!\s)/gm, '$& ')
      formatted = formatted.replace(/^(\d+)\.(?!\s)/gm, '$& ')

      // 确保段落之间有换行
      formatted = formatted.replace(/\n{3,}/g, '\n\n')

      // 更新文档内容
      if (mode === 'create') {
        this.documentForm.content = formatted
      } else {
        this.editDocumentForm.content = formatted
      }
    },

    // 登录方法
    async login() {
      try {
        // 创建表单数据
        const formData = new FormData()
        formData.append('username', this.loginForm.username)
        formData.append('password', this.loginForm.password)
        
        const response = await axios.post(`${this.API_BASE_URL}/auth/token`, formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        })
        
        // 保存token到localStorage
        localStorage.setItem('authToken', response.data.access_token)
        
        // 更新登录状态
        this.isLoggedIn = true
        this.loginMessage = ''
        
        // 清空登录表单
        this.loginForm = {
          username: '',
          password: ''
        }
        
        // 初始化应用
        this.initApp()
      } catch (error) {
        console.error('登录失败:', error)
        this.loginMessage = '登录失败：用户名或密码错误'
        this.isLoggedIn = false
      }
    },
    
    // 登出方法
    async logout() {
      try {
        // 获取token
        const token = localStorage.getItem('authToken')
        if (token) {
          // 调用后端登出接口
          await axios.post(`${this.API_BASE_URL}/auth/logout`, {}, {
            headers: {
              'Authorization': `Bearer ${token}`
            }
          })
        }
        
        // 移除token
        localStorage.removeItem('authToken')
        
        // 更新登录状态
        this.isLoggedIn = false
        
        // 重置应用状态
        this.categories = []
        this.recentDocuments = []
        this.searchResults = []
        this.totalDocuments = 0
      } catch (error) {
        console.error('登出失败:', error)
        // 即使后端请求失败，也执行本地登出操作
        localStorage.removeItem('authToken')
        this.isLoggedIn = false
        this.categories = []
        this.recentDocuments = []
        this.searchResults = []
        this.totalDocuments = 0
      }
    },
    
    // 检查登录状态
    async checkLoginStatus() {
      const token = localStorage.getItem('authToken')
      if (!token) {
        this.isLoggedIn = false
        return
      }
      
      try {
        // 验证token是否有效（使用GET方法）
        await axios.get(`${this.API_BASE_URL}/auth/verify`)
        this.isLoggedIn = true
      } catch (error) {
        console.error('验证登录状态失败:', error)
        localStorage.removeItem('authToken')
        this.isLoggedIn = false
      }
    },
    
    // 搜索文档
    async searchDocuments() {
      const query = this.searchQuery.trim()

      if (!query) {
        this.showErrorToast('请输入搜索关键词')
        return
      }

      try {
        this.searchLoading = true
        const response = await axios.post(`${this.API_BASE_URL}/search/`, {
          query,
          top_k: 10,
          category_id: this.searchCategoryId || null
        })
        this.searchResults = response.data
      } catch (error) {
        console.error('搜索失败:', error)
        this.searchResults = []
        this.showErrorToast('搜索失败: ' + (error.response?.data?.detail || error.message))
      } finally {
        this.searchLoading = false
      }
    },

    // 获取分类下的文档
    async getDocumentsByCategory(categoryId) {
      try {
        this.searchLoading = true
        const response = await axios.get(`${this.API_BASE_URL}/documents/category/${categoryId}`)
        // 为了复用搜索结果展示，我们给每个文档添加一个相似度字段
        this.searchResults = response.data.map(doc => ({
          ...doc,
          similarity: 1.0
        }))
        // 更新搜索框状态
        this.searchCategoryId = categoryId.toString()
      } catch (error) {
        console.error('获取文档失败:', error)
        this.searchResults = []
        this.showErrorToast('获取文档失败: ' + (error.response?.data?.detail || error.message))
      } finally {
        this.searchLoading = false
      }
    },

    // 加载最近文档
    async loadRecentDocuments() {
      try {
        this.recentDocumentsLoading = true
        // 假设我们获取10个最近的文档
        const response = await axios.get(`${this.API_BASE_URL}/documents/`)
        // 按更新时间排序，取前10个
        this.recentDocuments = response.data
          .sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at))
          .slice(0, 10)
      } catch (error) {
        console.error('获取最近文档失败:', error)
        this.recentDocuments = []
      } finally {
        this.recentDocumentsLoading = false
      }
    },

    // 聊天功能相关方法
    async loadConversations(documentId) {
      try {
        this.loadingConversation = true
        const response = await axios.get(`${this.API_BASE_URL}/chat/document/${documentId}`)
        this.conversations = response.data
      } catch (error) {
        console.error('获取对话列表失败:', error)
        this.conversations = []
        this.showErrorToast('获取对话列表失败')
      } finally {
        this.loadingConversation = false
      }
    },

    async createNewConversation(documentId) {
      try {
        this.loadingConversation = true
        const response = await axios.post(`${this.API_BASE_URL}/chat/document/${documentId}`, {
          title: '新对话'
        })
        // 重新加载对话列表
        await this.loadConversations(documentId)
        // 切换到新创建的对话
        this.switchConversation(response.data.id)
        this.showSuccessToast('对话创建成功')
      } catch (error) {
        console.error('创建对话失败:', error)
        this.showErrorToast('创建对话失败')
      } finally {
        this.loadingConversation = false
      }
    },

    // 智能分类文档
    async smartCategorize() {
      try {
        this.searchLoading = true
        // 确定当前是新增文档还是编辑文档模式
        const isEditMode = this.editDocumentModalVisible
        const content = isEditMode ? this.editDocumentForm.content : this.documentForm.content

        const response = await axios.post(`${this.API_BASE_URL}/documents/smart-categorize`, {
          content: content
        })

        this.suggestedCategories = response.data.categories
        this.selectedCategories = [] // 重置选中状态
        this.smartCategoriesModalVisible = true
      } catch (error) {
        console.error('智能分类失败:', error)
        this.showErrorToast('智能分类失败: ' + (error.response?.data?.detail || error.message))
      } finally {
        this.searchLoading = false
      }
    },

    // 确认智能分类结果
    async confirmSmartCategories() {
      try {
        // 筛选出用户选择的分类
        const selectedCategoryNames = this.selectedCategories

        // 检查哪些是新分类，需要创建
        const newCategories = []
        const existingCategoryIds = []

        for (const category of this.suggestedCategories) {
          if (this.selectedCategories.includes(category.name)) {
            if (category.is_existing) {
              existingCategoryIds.push(category.id)
            } else {
              newCategories.push(category.name)
            }
          }
        }

        // 创建新分类
        const allCategoryIds = [...existingCategoryIds]
        for (const categoryName of newCategories) {
          try {
            const response = await axios.post(`${this.API_BASE_URL}/categories/`, {
              name: categoryName,
              description: `由智能分类生成的分类：${categoryName}`
            })
            allCategoryIds.push(response.data.id)
          } catch (error) {
            console.error(`创建分类 ${categoryName} 失败:`, error)
            // 继续尝试创建其他分类
          }
        }

        // 确定当前是新增文档还是编辑文档模式
        const isEditMode = this.editDocumentModalVisible

        // 更新文档表单的分类
        // 合并现有选择和新选择的分类，避免重复
        if (isEditMode) {
          const mergedCategoryIds = [...new Set([...this.editDocumentForm.categoryIds, ...allCategoryIds])]
          this.editDocumentForm.categoryIds = mergedCategoryIds
        } else {
          const mergedCategoryIds = [...new Set([...this.documentForm.categoryIds, ...allCategoryIds])]
          this.documentForm.categoryIds = mergedCategoryIds
        }

        // 更新分类列表
        await this.updateCategories()

        // 关闭模态框
        this.smartCategoriesModalVisible = false
        this.showSuccessToast('智能分类已应用')
      } catch (error) {
        console.error('应用智能分类失败:', error)
        this.showErrorToast('应用智能分类失败: ' + (error.response?.data?.detail || error.message))
      }
    },

    async switchConversation(conversationId) {
      try {
        this.loadingConversation = true
        this.currentConversation = this.conversations.find(conv => conv.id === conversationId)
        // 获取对话消息
        const response = await axios.get(`${this.API_BASE_URL}/chat/${conversationId}/messages`)
        this.messages = response.data
      } catch (error) {
        console.error('获取对话消息失败:', error)
        this.messages = []
        this.showErrorToast('获取对话消息失败')
      } finally {
        this.loadingConversation = false
      }
    },

    async sendMessage() {
      if (!this.newMessage.trim() || !this.currentConversation || this.sendingMessage) {
        return
      }

      try {
        this.sendingMessage = true
        const messageContent = this.newMessage.trim()

        // 添加用户消息到消息列表（乐观更新）
        const userMessage = {
          id: Date.now(), // 临时ID
          role: 'user',
          content: messageContent,
          created_at: new Date().toISOString()
        }
        this.messages.push(userMessage)

        // 滚动到底部
        this.scrollToBottom()

        // 清空输入框
        this.newMessage = ''

        // 强制Vue更新视图，确保用户消息立即显示
        this.$nextTick()

        // 发送消息到服务器并获取AI回复
        const response = await axios.post(`${this.API_BASE_URL}/chat/${this.currentConversation.id}/messages`, {
          content: messageContent
        })

        // 添加AI回复到消息列表
        if (response.data && response.data.role === 'assistant') {
          this.messages.push(response.data)
          // 在添加AI回复后立即滚动到底部
          this.$nextTick(() => {
            this.scrollToBottom()
          })
        }

        // 更新对话列表中的更新时间并重新排序
        const convIndex = this.conversations.findIndex(conv => conv.id === this.currentConversation.id)
        if (convIndex !== -1) {
          // 创建一个新的对话对象以确保响应式更新
          const updatedConversation = {
            ...this.conversations[convIndex],
            updated_at: new Date().toISOString()
          }

          // 创建新数组，先删除原对话，再添加更新后的对话到开头
          const newConversations = [...this.conversations]
          newConversations.splice(convIndex, 1)
          newConversations.unshift(updatedConversation)

          // 赋值给this.conversations以触发响应式更新
          this.conversations = newConversations
        }


      } catch (error) {
        console.error('发送消息失败:', error)
        // 移除刚才添加的临时消息
        const index = this.messages.findIndex(msg => msg.id === userMessage.id)
        if (index !== -1) {
          this.messages.splice(index, 1)
        }
        this.showErrorToast('发送消息失败')
      } finally {
        this.sendingMessage = false
        // 确保无论是否成功，都会滚动到底部显示最新消息
        this.$nextTick(() => {
          this.scrollToBottom()
        })
      }
    },

    // 滚动到消息容器底部
    scrollToBottom() {
      this.$nextTick(() => {
        const messagesContainer = document.getElementById('messagesContainer')
        if (messagesContainer) {
          messagesContainer.scrollTop = messagesContainer.scrollHeight
        }
      })
    },

    // 显示删除对话确认模态框
    showDeleteConversationModal(conversationId, conversationTitle) {
      this.renameConversationModalVisible = false
      this.currentOperationConversationId = conversationId
      this.currentOperationConversationTitle = conversationTitle
      this.deleteConversationModalVisible = true
    },

    // 隐藏删除对话确认模态框
    hideDeleteConversationModal() {
      this.deleteConversationModalVisible = false
      this.currentOperationConversationId = null
      this.currentOperationConversationTitle = ''
    },

    // 确认删除对话
    async confirmDeleteConversation() {
      try {
        await axios.delete(`${this.API_BASE_URL}/chat/${this.currentOperationConversationId}`)
        // 重新加载对话列表
        await this.loadConversations(this.currentDocument.id)
        // 如果删除的是当前对话，则清除当前对话
        if (this.currentConversation && this.currentConversation.id === this.currentOperationConversationId) {
          this.currentConversation = null
          this.messages = []
        }
        if (this.conversations.length > 0) {
          this.switchConversation(this.conversations[0].id)
        }
        this.hideDeleteConversationModal()
        this.showSuccessToast('对话删除成功')
      } catch (error) {
        console.error('删除对话失败:', error)
        this.showErrorToast('删除对话失败')
      }
    },

    // 显示重命名对话模态框
    showRenameConversationModal(conversationId, currentTitle) {
      this.currentOperationConversationId = conversationId
      this.currentOperationConversationTitle = currentTitle
      this.newConversationTitle = currentTitle
      this.renameConversationModalVisible = true
    },

    // 隐藏重命名对话模态框
    hideRenameConversationModal() {
      this.renameConversationModalVisible = false
      this.currentOperationConversationId = null
      this.currentOperationConversationTitle = ''
      this.newConversationTitle = ''
    },

    // 确认重命名对话
    async confirmRenameConversation() {
      if (!this.newConversationTitle.trim()) {
        return
      }

      try {
        await axios.put(`${this.API_BASE_URL}/chat/${this.currentOperationConversationId}/title`, {
          title: this.newConversationTitle.trim()
        })
        // 更新本地对话列表中的标题
        const conversation = this.conversations.find(conv => conv.id === this.currentOperationConversationId)
        if (conversation) {
          conversation.title = this.newConversationTitle.trim()
        }
        // 如果是当前对话，也更新当前对话的标题
        if (this.currentConversation && this.currentConversation.id === this.currentOperationConversationId) {
          this.currentConversation.title = this.newConversationTitle.trim()
        }
        this.hideRenameConversationModal()
      } catch (error) {
        console.error('更新对话标题失败:', error)
        this.showErrorToast('更新对话标题失败')
      }
    },

    // 重命名对话（双击标题时触发）
    renameConversation(conversationId, currentTitle) {
      this.showRenameConversationModal(conversationId, currentTitle)
    },

    // 更新统计信息
    async updateStatistics() {
      try {
        const response = await axios.get(`${this.API_BASE_URL}/documents/count`)
        this.totalDocuments = response.data.total_documents
      } catch (error) {
        console.error('获取统计信息失败:', error)
        this.totalDocuments = 0
      }
    },

    // 显示文档详情
    async showDocumentDetail(documentId) {
      try {
        const response = await axios.get(`${this.API_BASE_URL}/documents/${documentId}`)
        this.currentDocument = response.data
        this.documentDetailModalVisible = true
        // 加载该文档的对话列表
        await this.loadConversations(documentId)
        // 如果有对话，默认选择第一个
        if (this.conversations.length > 0) {
          this.switchConversation(this.conversations[0].id)
        } else {
          // 如果没有对话，重置当前对话和消息
          this.currentConversation = null
          this.messages = []
        }
      } catch (error) {
        console.error('获取文档详情失败:', error)
        this.showErrorToast('获取文档详情失败: ' + (error.response?.data?.detail || error.message))
      }
    },

    // 隐藏文档详情模态框
    hideDocumentDetailModal() {
      this.documentDetailModalVisible = false
      this.currentDocument = null
    },

    // 确认删除文档
    confirmDeleteDocument() {
      if (confirm('确定要删除这个文档吗？删除后将无法恢复。')) {
        this.deleteDocument(this.currentDocument.id)
      }
    },

    // 显示编辑文档模态框
    showEditDocumentModal() {
      // 填充编辑表单
      this.editDocumentForm = {
        id: this.currentDocument.id,
        title: this.currentDocument.title || '',
        content: this.currentDocument.content,
        categoryIds: this.currentDocument.category_ids || []
      }

      // 关闭详情模态框，显示编辑模态框
      this.hideDocumentDetailModal()
      this.editDocumentModalVisible = true
    },

    // 隐藏编辑文档模态框
    hideEditDocumentModal() {
      this.editDocumentModalVisible = false
      this.editDocumentForm = {
        id: null,
        title: '',
        content: '',
        categoryIds: []
      }
    },

    // 处理保存编辑后的文档
    async handleSaveEditDocument() {
      const title = this.editDocumentForm.title.trim()
      const content = this.editDocumentForm.content.trim()
      const categoryIds = this.editDocumentForm.categoryIds.length > 0 ? this.editDocumentForm.categoryIds : []

      if (!content) {
        this.showErrorToast('请输入文档内容')
        return
      }

      const success = await this.updateDocument(
        this.editDocumentForm.id,
        title,
        content,
        categoryIds
      )

      if (success) {
        // 重置排版状态
        this.canUndo = false
        this.hideEditDocumentModal()
      }
    },

    // 获取分类名称
    getCategoryName(categoryId) {
      // 处理类型不匹配的情况，确保能找到对应的分类
      const category = this.categories.find(cat =>
        String(cat.id) === String(categoryId)
      )
      return category ? category.name : '未分类'
    },

    // 截断文本
    truncateText(text, maxLength = 100) {
      if (!text) return ''
      if (text.length <= maxLength) return text
      // 确保不会在Markdown语法中间截断
      let truncated = text.substring(0, maxLength)
      // 简单处理：避免在代码块、链接或强调语法中间截断
      const lastSpaceIndex = truncated.lastIndexOf(' ')
      if (lastSpaceIndex > maxLength * 0.7) {
        truncated = truncated.substring(0, lastSpaceIndex)
      }
      return truncated + '...'
    },

    // 格式化日期
    formatDate(dateString) {
      if (!dateString) return ''
      const date = new Date(dateString)
      return new Intl.DateTimeFormat('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit'
      }).format(date)
    },

    // 显示成功提示
    showSuccessToast(message = '操作成功') {
      this.toast = {
        visible: true,
        message,
        type: 'success'
      }

      setTimeout(() => {
        this.toast.visible = false
      }, 3000)
    },

    // 显示错误提示
    showErrorToast(message = '操作失败') {
      this.toast = {
        visible: true,
        message,
        type: 'error'
      }

      setTimeout(() => {
        this.toast.visible = false
      }, 3000)
    },

    // 更新文档
    async updateDocument(documentId, title, content, categoryIds) {
      try {
        const response = await axios.put(`${this.API_BASE_URL}/documents/${documentId}`, {
          title,
          content,
          category_ids: categoryIds
        })

        // 更新当前文档（如果正在查看）
        if (this.currentDocument && this.currentDocument.id === documentId) {
          this.currentDocument = response.data
        }

        // 更新统计、最近文档和分类文档数量
        await this.updateStatistics()
        await this.loadRecentDocuments()
        await this.updateCategories()

        // 重置排版状态
        this.canUndo = false
        this.showSuccessToast('文档更新成功')
        return true
      } catch (error) {
        console.error('更新文档失败:', error)
        this.showErrorToast('更新文档失败: ' + (error.response?.data?.detail || error.message))
        return false
      }
    },

    // 删除文档
    async deleteDocument(documentId) {
      try {
        await axios.delete(`${this.API_BASE_URL}/documents/${documentId}`)

        // 如果正在查看的是被删除的文档，则关闭详情模态框
        if (this.currentDocument && this.currentDocument.id === documentId) {
          this.hideDocumentDetailModal()
        }

        // 更新统计、最近文档和分类文档数量
        await this.updateStatistics()
        await this.loadRecentDocuments()
        await this.updateCategories()

        this.showSuccessToast('文档删除成功')
        return true
      } catch (error) {
        console.error('删除文档失败:', error)
        this.showErrorToast('删除文档失败: ' + (error.response?.data?.detail || error.message))
        return false
      }
    },

    // 渲染Markdown内容
    renderMarkdown(content) {
      if (!content) return ''
      try {
        // 调试列表渲染
        if (content.includes('- ') || content.includes('* ') || /\d+\./.test(content)) {
          console.log('检测到列表内容:', content)
        }

        // 使用配置好的marked实例解析Markdown内容
        const result = marked.parse(content, {
          breaks: true, // 换行符转换为<br>
          gfm: true,    // 启用GitHub风格的Markdown
          headerIds: true,
          mangle: false,
          // 确保列表正确渲染的额外选项
          lists: true,
          smartLists: true,
          // 确保嵌套列表的序号正确重排
          smartypants: false,
          // 增加解析列表的严格性
          silent: false
        })

        // 调试渲染结果
        if (content.includes('- ') || content.includes('* ') || /\d+\./.test(content)) {
          console.log('渲染结果:', result)
        }

        return result
      } catch (error) {
        console.error('Markdown渲染失败:', error)
        return content
      }
    },

    // 初始化MathJax
    initMathJax() {
      if (window.MathJax) return

      // 创建MathJax配置
      const script = document.createElement('script')
      script.src = 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js'
      script.async = true

      // MathJax配置
      const config = document.createElement('script')
      config.textContent = `
        window.MathJax = {
          tex: {
            inlineMath: [['$', '$'], ['\\(', '\\)']],
            displayMath: [['$$', '$$'], ['\\[', '\\]']],
            packages: ['base', 'ams', 'noerrors', 'noundefined']
          },
          svg: {
            fontCache: 'global'
          },
          startup: {
            typeset: false // 延迟自动渲染，等待我们手动触发
          }
        };
      `

      document.head.appendChild(config)
      document.head.appendChild(script)
    },

    // 触发MathJax重新渲染
    renderMathJax() {
      if (window.MathJax) {
        window.MathJax.typesetPromise().catch((err) => {
          console.error('MathJax渲染失败:', err)
        })
      }
    },

    // 切换主题
    toggleTheme() {
      if (this.darkMode) {
        this.disableDarkMode()
      } else {
        this.enableDarkMode()
      }
    },

    // 启用暗黑模式
    enableDarkMode() {
      document.documentElement.setAttribute('data-theme', 'dark')
      localStorage.setItem('theme', 'dark')
      this.darkMode = true
      // 切换到暗黑模式代码高亮样式
      this.loadHighlightStyles()
    },

    // 禁用暗黑模式
    disableDarkMode() {
      document.documentElement.setAttribute('data-theme', 'light')
      localStorage.setItem('theme', 'light')
      this.darkMode = false
      // 切换到浅色模式代码高亮样式
      this.loadHighlightStyles()
    },

    // 初始化主题
    initTheme() {
      if (this.darkMode) {
        this.enableDarkMode()
      } else {
        this.disableDarkMode()
      }
    },

    // 滚动到文本输入区域
    scrollToAddDocument() {
      const element = document.getElementById('addDocumentDiv');
      if (element) {
        // 计算滚动位置，留出一定的顶部空间
        const topOffset = 80;
        const elementPosition = element.getBoundingClientRect().top;
        const offsetPosition = elementPosition + window.pageYOffset - topOffset;
        
        // 平滑滚动
        window.scrollTo({
          top: offsetPosition,
          behavior: 'smooth'
        });
      }
    },

    // 加载highlight.js样式
    loadHighlightStyles() {
      // 移除已存在的highlight.js样式链接
      const existingStyles = document.querySelectorAll('link[href*="highlight.js/styles/"]')
      existingStyles.forEach(style => style.remove())

      // 根据当前主题创建新的样式链接
      const styleLink = document.createElement('link')
      styleLink.rel = 'stylesheet'
      styleLink.href = this.darkMode
        ? '/node_modules/highlight.js/styles/tomorrow-night-bright.css'
        : '/node_modules/highlight.js/styles/github.css'
      document.head.appendChild(styleLink)
    },
  },


}
</script>